import socket
import time
import xml.etree.ElementTree as ET
from datetime import datetime, timedelta
import json
from apscheduler.schedulers.background import BackgroundScheduler

from APN1_2_1.fod.base_fod import get_start_time_from_user, generate_random_lat_lon


def build_xml(
        fod_id,
        ddtm_value,
        time_value,
        start_lat: float = 37.8125056,
        start_lon: float = -122.3874432,
):
    """
    构建指定格式的XML文档，时间相关内容可传入参数动态设置，并添加XML声明

    :param ddtm_value: DDTM元素对应的时间值，格式需符合要求（如示例中的格式）
    :param time_value: TIME元素对应的时间值，格式需符合要求（如示例中的格式）
    :return: 构建好的XML字符串
    """
    xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>'
    root = ET.Element("MSG")
    meta = ET.SubElement(root, "META")
    sndr = ET.SubElement(meta, "SNDR")
    sndr.text = "FOD"
    rcvr = ET.SubElement(meta, "RCVR")
    seqn = ET.SubElement(meta, "SEQN")
    seqn.text = "56208"
    ddtm = ET.SubElement(meta, "DDTM")
    ddtm.text = str(ddtm_value)
    sorc = ET.SubElement(meta, "SORC")
    mgid = ET.SubElement(meta, "MGID")
    mgid.text = "fod_755024616803667969"
    rmid = ET.SubElement(meta, "RMID")
    apot = ET.SubElement(meta, "APOT")
    apot.text = "ZUUU"
    fod = ET.SubElement(root, "FOD")
    id_elem = ET.SubElement(fod, "ID")
    id_elem.text = fod_id
    runwayid = ET.SubElement(fod, "RUNWAYID")
    runwayid.text = "02R/02L"
    deviceid = ET.SubElement(fod, "DEVICEID")
    deviceid.text = "W10"
    lon = ET.SubElement(fod, "LON")
    lon.text = str(start_lon)
    lat = ET.SubElement(fod, "LAT")
    lat.text = str(start_lat)
    x = ET.SubElement(fod, "X")
    x.text = "234.67"
    y = ET.SubElement(fod, "Y")
    y.text = "32.78"
    size = ET.SubElement(fod, "SIZE")
    size.text = "0.5*1.2"
    type_elem = ET.SubElement(fod, "TYPE")
    type_elem.text = "鸟"
    disposal = ET.SubElement(fod, "DISPOSAL")
    disposal.text = "未处置"
    time_elem = ET.SubElement(fod, "TIME")
    time_elem.text = str(time_value)
    tree = ET.ElementTree(root)
    xml_str = ET.tostring(root, encoding="utf-8", method="xml").decode("utf-8")
    full_xml_str = xml_declaration + "\n" + xml_str
    return full_xml_str


def build_bird(
        fod_id: int = 5,
        ddtm_value: str = "20240228050618502",
        time_value: str = "20240228051300",
        start_lat: float = 29.7388888,
        start_lon: float = 106.7138888,
        radius_km: float = 0.2,
        fixed_bird_msg: list = None,
):
    ls_msg = []
    if fod_id > 1:
        for i in range(1, fod_id + 1):
            fod_id = format_fod_id(i)
            start_lat, start_lon = generate_random_lat_lon(start_lat, start_lon, radius_km)
            result_xml = build_xml(
                fod_id,
                ddtm_value=ddtm_value,
                time_value=time_value,
                start_lat=start_lat,
                start_lon=start_lon,
            )
            ls_msg.append(result_xml)
    if fixed_bird_msg:
        ls_msg.extend(fixed_bird_msg)
    data = {
        "code": 0,
        "msg": None,
        "data": {
            "bootSuccess": True,
            "bootState": "200",
            "bootStateDesc": None,
            "msg": ls_msg,
        },
    }
    return "ZCZC " + json.dumps(data) + " NNNN"


def build_bird_msg_with_xml(ls_xml: list):
    data = {
        "code": 0,
        "msg": None,
        "data": {
            "bootSuccess": True,
            "bootState": "200",
            "bootStateDesc": None,
            "msg": ls_xml,
        },
    }
    return "ZCZC " + json.dumps(data) + " NNNN"


def format_fod_id(fod_id: int, len_fod_id: int = 5):
    __id = "0"
    fod_id = str(fod_id)
    __len_fod_id = len(fod_id)
    return __id * (len_fod_id - __len_fod_id) + fod_id


def client_connect():
    """
    客户端连接服务器并定时向服务端发送build_bird返回的内容的函数
    """
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_address = ("192.168.227.60", 56001)
    client_socket.connect(server_address)
    print("已连接到服务器")

    scheduler = BackgroundScheduler()
    start_time = get_start_time_from_user()
    current_time = start_time
    sending_cycle = 30  # 发送周期
    num_bird = 20  # 发送鸟情数量
    start_lat: float = 29.7276  # 20L附近 # 29.7082 # 02L附近  # 随机的起始经纬度
    start_lon: float = 106.645  # 20L附近 # 106.638  # 02L附近 随机的起始经纬度
    radius_km: float = 0.2  # 随机生成范围，在上述起始点范围内

    dict_bird_msg_lat_lon = {}
    for bird in range(1, num_bird + 1):
        start_lat, start_lon = generate_random_lat_lon(start_lat, start_lon, radius_km)
        dict_bird_msg_lat_lon[bird] = start_lat, start_lon

    def send_data():
        nonlocal current_time
        # 将时间递增（这里以秒为单位，可根据需求调整时间变化粒度）
        current_time = (current_time + timedelta(seconds=sending_cycle)).strftime(
            "%Y%m%d%H%M%S"
        )
        print(dict_bird_msg_lat_lon)

        # 这一段每个周期发送固定点的鸟情
        ls_bird_msg = []
        for __bird in range(1, num_bird + 1):
            ls_bird_msg.append(
                build_xml(
                    fod_id=format_fod_id(num_bird + __bird),
                    ddtm_value=str(current_time),
                    time_value=str(current_time),
                    start_lat=dict_bird_msg_lat_lon[__bird][0],
                    start_lon=dict_bird_msg_lat_lon[__bird][1],
                )
            )

        #  这一段每个周期随机生成不同位置的鸟情
        sport_num_bird = num_bird
        data = build_bird(
            sport_num_bird,
            current_time,
            current_time,
            start_lat=start_lat,
            start_lon=start_lon,
            radius_km=radius_km,
            fixed_bird_msg=ls_bird_msg,
        )
        client_socket.send(data.encode("utf-8"))
        current_time = datetime.strptime(current_time, "%Y%m%d%H%M%S")
        print(f"已向服务器发送数据 {data}")

    send_data()
    # 添加定时任务，这里设置每隔1秒执行一次send_data函数，可根据需求调整时间间隔
    scheduler.add_job(send_data, "interval", seconds=sending_cycle)
    scheduler.start()

    try:
        # 让主线程保持运行，避免程序退出，这里可以添加其他需要持续运行的逻辑
        while True:
            time.sleep(1)
    except (KeyboardInterrupt, SystemExit):
        # 捕获中断信号，关闭调度器，释放资源
        scheduler.shutdown()


if __name__ == "__main__":
    client_connect()
